home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / Obrn-A_1.6_lib.lha / oberon-a / source3.lha / source / AmigaUtil / IntuiUtil.mod < prev    next >
Text File  |  1995-06-29  |  17KB  |  657 lines

  1. (***************************************************************************
  2.  
  3.      $RCSfile: IntuiUtil.mod $
  4.   Description: Support for clients of intuition.library
  5.  
  6.    Created by: fjc (Frank Copeland)
  7.     $Revision: 3.8 $
  8.       $Author: fjc $
  9.         $Date: 1995/06/04 23:18:08 $
  10.  
  11.   Copyright © 1994-1995, Frank Copeland.
  12.   This file is part of the Oberon-A Library.
  13.   See Oberon-A.doc for conditions of use and distribution.
  14.  
  15. ***************************************************************************)
  16.  
  17. <* STANDARD- *>
  18.  
  19. MODULE IntuiUtil;
  20.  
  21. IMPORT
  22.   SYS := SYSTEM, e := Exec, gfx := Graphics, l := Layers, i := Intuition,
  23.   u := Util;
  24.  
  25.  
  26. (* Passed as a parameter to GetMenuChoice () *)
  27.  
  28. TYPE
  29.  
  30.   Choice * = RECORD
  31.     menuChosen *    : INTEGER;
  32.     itemChosen *    : INTEGER;
  33.     subItemChosen * : INTEGER;
  34.     pointer *       : i.MenuItemPtr;
  35.   END; (* ChoiceType *)
  36.  
  37. CONST
  38.  
  39.   halfPot  = i.maxPot DIV 2;
  40.   halfBody = i.maxBody DIV 2;
  41.  
  42. VAR
  43.   autoIntuiText : i.IntuiText;
  44.  
  45.  
  46. (* ===== Preferences ===== *)
  47.  
  48.  
  49. (*------------------------------------*)
  50. PROCEDURE PrefsFontHeight * () : SHORTINT;
  51. (*
  52.   Returns the height of the default system font.
  53. *)
  54.  
  55. VAR
  56.   prefsBuffer : i.Preferences;
  57.  
  58. BEGIN
  59.   i.GetPrefs (prefsBuffer, SIZE(i.Preferences));
  60.   RETURN prefsBuffer.fontHeight;
  61. END PrefsFontHeight;
  62.  
  63.  
  64. (* ===== Gadget ===== *)
  65.  
  66.  
  67. (*------------------------------------*)
  68. PROCEDURE CentreGadget *
  69.   ( VAR gadget : i.Gadget; left, top, width, height : INTEGER );
  70. (*
  71.   Adjusts the gadget's position to centre it within a rectangle defined by
  72.   (left, top, width, height).
  73. *)
  74.  
  75. BEGIN (* CentreGadget *)
  76.   gadget.leftEdge := ( ( width - gadget.width ) DIV 2 ) + left;
  77.   gadget.topEdge := ( ( height - gadget.height ) DIV 2 ) + top;
  78. END CentreGadget;
  79.  
  80.  
  81. (*------------------------------------*)
  82. PROCEDURE ConvertPot *
  83.   ( potValue, totalUnits, visibleUnits : INTEGER )
  84.   : INTEGER;
  85.  
  86. VAR
  87.   value, hidden : LONGINT;
  88.  
  89. BEGIN (* ConvertPot *)
  90.   IF (potValue = 0) THEN
  91.     RETURN 0
  92.   ELSE
  93.     IF (visibleUnits >= totalUnits) THEN
  94.       RETURN 0
  95.     ELSE
  96.       IF potValue < 0 THEN value := potValue + 010000H
  97.       ELSE value := potValue
  98.       END;
  99.       hidden := totalUnits - visibleUnits;
  100.       RETURN SHORT ((hidden * value + halfPot) DIV i.maxPot)
  101.     END; (* ELSE *)
  102.   END; (* ELSE *)
  103. END ConvertPot;
  104.  
  105.  
  106. (*------------------------------------*)
  107. PROCEDURE ConvertToPot *
  108.   ( units, totalUnits, visibleUnits : INTEGER )
  109.   : INTEGER;
  110.  
  111. VAR
  112.   hidden, lUnits : LONGINT;
  113.  
  114. BEGIN (* ConvertToPot *)
  115.   IF units = 0 THEN
  116.     RETURN 0
  117.   ELSE
  118.     IF visibleUnits >= totalUnits THEN
  119.       RETURN 0
  120.     ELSE
  121.       IF units < 0 THEN lUnits := units + 010000H
  122.       ELSE lUnits := units
  123.       END;
  124.       hidden := totalUnits - visibleUnits;
  125.       IF lUnits >= hidden THEN
  126.         RETURN -1 (*i.maxPot*)
  127.       ELSE
  128.         RETURN SHORT ((i.maxPot * lUnits) DIV hidden)
  129.       END; (* ELSE *)
  130.     END; (* ELSE *)
  131.   END; (* ELSE *)
  132. END ConvertToPot;
  133.  
  134.  
  135. (*------------------------------------*)
  136. PROCEDURE ConvertBody * (bodyValue, totalUnits : INTEGER) : INTEGER;
  137.  
  138.   VAR value : LONGINT;
  139.  
  140. BEGIN (* ConvertBody *)
  141.   IF bodyValue = 0 THEN
  142.     RETURN 0
  143.   ELSIF (bodyValue = i.maxBody) OR (totalUnits < 2) THEN
  144.     RETURN totalUnits
  145.   ELSE
  146.     IF bodyValue < 0 THEN value := bodyValue + 010000H
  147.     ELSE value := bodyValue
  148.     END;
  149.     RETURN SHORT ((totalUnits * value) DIV i.maxBody);
  150.   END
  151. END ConvertBody;
  152.  
  153.  
  154. (*------------------------------------*)
  155. PROCEDURE ConvertToBody * ( totalUnits, visibleUnits : INTEGER ) : INTEGER;
  156.  
  157. BEGIN (* ConvertToBody *)
  158.   IF visibleUnits = 0 THEN
  159.     RETURN 0
  160.   ELSIF visibleUnits >= totalUnits THEN
  161.     RETURN -1 (*i.maxBody*)
  162.   ELSE
  163.     RETURN SHORT ((i.maxBody * visibleUnits) DIV totalUnits)
  164.   END; (* ELSE *)
  165. END ConvertToBody;
  166.  
  167.  
  168. (*------------------------------------*)
  169. PROCEDURE SetString * (VAR gadget : i.Gadget; string : ARRAY OF CHAR);
  170.  
  171. VAR
  172.   stringInfo : i.StringInfoPtr;
  173.  
  174. <*$CopyArrays-*>
  175. BEGIN (* SetString *)
  176.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  177.   SYS.MOVE
  178.     ( SYS.ADR (string), stringInfo.buffer,
  179.       u.MaxInt
  180.         ( SHORT (SYS.STRLEN (string) + 1), stringInfo.maxChars - 1 ) );
  181.   stringInfo.buffer [stringInfo.maxChars] := 0X
  182. END SetString;
  183.  
  184.  
  185. (*------------------------------------*)
  186. PROCEDURE GetString *  (VAR gadget : i.Gadget; VAR string : ARRAY OF CHAR);
  187.  
  188. VAR
  189.   stringInfo : i.StringInfoPtr;
  190.  
  191. BEGIN (* SetString *)
  192.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  193.   COPY (stringInfo.buffer^, string)
  194. END GetString;
  195.  
  196.  
  197. (*------------------------------------*)
  198. PROCEDURE SetInteger * ( VAR gadget : i.Gadget; integer : LONGINT );
  199.  
  200.   VAR
  201.     stringInfo : i.StringInfoPtr;
  202.     buffer : ARRAY 12 OF CHAR;
  203.     index : INTEGER;
  204.     negative : BOOLEAN;
  205.  
  206.   (*------------------------------------*)
  207.   PROCEDURE Digits ( integer : LONGINT ) : INTEGER;
  208.  
  209.   VAR
  210.     digits : INTEGER;
  211.  
  212.   BEGIN (* Digits *)
  213.     digits := 0;
  214.     WHILE ( integer > 0 ) DO
  215.       INC( digits );
  216.       integer := integer DIV 10;
  217.     END; (* WHILE *)
  218.     RETURN digits;
  219.   END Digits;
  220.  
  221. BEGIN (* SetInteger *)
  222.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  223.   stringInfo.longInt := integer;
  224.   negative := (integer < 0); integer := ABS(integer);
  225.   index := Digits( integer );
  226.   IF negative THEN INC(index) END;
  227.   buffer [index] := 0X;
  228.   WHILE integer > 0 DO
  229.     DEC (index);
  230.     buffer[index] := CHR (integer MOD 10 + ORD ("0"));
  231.     integer := integer DIV 10;
  232.   END; (* WHILE *)
  233.   IF negative THEN buffer [0] := "-" END;
  234.   SetString (gadget, buffer);
  235. END SetInteger;
  236.  
  237.  
  238. (*------------------------------------*)
  239. PROCEDURE GetInteger * ( VAR gadget : i.Gadget ) : LONGINT;
  240.  
  241. VAR
  242.   stringInfo : i.StringInfoPtr;
  243.  
  244. BEGIN (* GetInteger *)
  245.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  246.   RETURN stringInfo^.longInt;
  247. END GetInteger;
  248.  
  249.  
  250. (* ===== IntuiText ===== *)
  251.  
  252.  
  253. (*------------------------------------*)
  254. PROCEDURE IntuiTextHeight * ( VAR intuiText : i.IntuiText ) : INTEGER;
  255. (*
  256.   Returns the height in scan lines of the text held in intuiText.
  257. *)
  258.  
  259. BEGIN (* IntuiTextHeight *)
  260.   IF intuiText.iTextFont = NIL THEN
  261.     RETURN PrefsFontHeight()
  262.   ELSE
  263.     RETURN intuiText.iTextFont.ySize
  264.   END; (* ELSE *)
  265. END IntuiTextHeight;
  266.  
  267.  
  268. (*------------------------------------*)
  269. PROCEDURE CentreIntuiText * (
  270.   VAR intuiText : i.IntuiText;
  271.   left, top, width, height : INTEGER );
  272. (*
  273.   Adjusts the text's position to centre it within a rectangle defined by
  274.   (left, top, width, height).
  275. *)
  276.  
  277. BEGIN (* CentreIntuiText *)
  278.   intuiText.leftEdge :=
  279.     ( ( width - i.IntuiTextLength(intuiText) ) DIV 2 ) + left;
  280.   intuiText.topEdge :=
  281.     ( ( height - IntuiTextHeight(intuiText) ) DIV 2 ) + top;
  282. END CentreIntuiText;
  283.  
  284.  
  285. (*------------------------------------*)
  286. PROCEDURE CalcTextBox *
  287.   ( text              : ARRAY OF CHAR;
  288.     font              : gfx.TextAttrPtr;
  289.     VAR width, height : INTEGER );
  290. (*
  291.   Returns the minimum size of the rectangle that will enclose the given text
  292.   if rendered in the given font.
  293. *)
  294.  
  295. VAR
  296.   intuiText : i.IntuiText;
  297.  
  298. <*$CopyArrays-*>
  299. BEGIN (* CalcTextBox *)
  300.   intuiText.iText := SYS.ADR (text);
  301.   intuiText.iTextFont := font;
  302.   width := i.IntuiTextLength (intuiText);
  303.   height := IntuiTextHeight (intuiText);
  304. END CalcTextBox;
  305.  
  306.  
  307. (* ===== Window ===== *)
  308.  
  309.  
  310. (*------------------------------------*)
  311. PROCEDURE ClipWindow *
  312.   ( window                 : i.WindowPtr;
  313.     minX, minY, maxX, maxY : INTEGER;
  314.     VAR oldRegion          : gfx.RegionPtr )
  315.   : BOOLEAN;
  316. (*
  317.   Sets up the window's clipping region to permit drawing only inside the
  318.   rectangle defined by (minX, minY, maxX, maxY). It returns FALSE if the
  319.   attempt fails and puts the existing clipping region in oldRegion.  It
  320.   should immediately be followed by drawing routines, then
  321.   UnclipWindow( window, oldRegion ).
  322. *)
  323.  
  324. VAR
  325.   newRegion : gfx.RegionPtr; myRectangle : gfx.Rectangle;
  326.  
  327. BEGIN (* ClipWindow *)
  328.   myRectangle.minX := minX;
  329.   myRectangle.minY := minY;
  330.   myRectangle.maxX := maxX;
  331.   myRectangle.maxY := maxY;
  332.   newRegion := gfx.NewRegion();
  333.   IF newRegion # NIL THEN
  334.     IF gfx.OrRectRegion (newRegion, myRectangle) THEN
  335.       oldRegion := l.InstallClipRegion (window.wLayer, newRegion);
  336.       RETURN TRUE;
  337.     END
  338.   END;
  339.   IF newRegion # NIL THEN
  340.     gfx.DisposeRegion (newRegion);
  341.   END;
  342.   RETURN FALSE;
  343. END ClipWindow;
  344.  
  345.  
  346. (*------------------------------------*)
  347. PROCEDURE ClipWindowToBorders *
  348.   ( window : i.WindowPtr; VAR oldRegion : gfx.RegionPtr )
  349.   : BOOLEAN;
  350. (*
  351.   Sets up the window's clipping region to permit drawing only inside the
  352.   rectangle defined by the window's borders.  It returns FALSE if the
  353.   attempt fails and puts the existing clipping region in oldRegion.  It
  354.   should immediately be followed by drawing routines, then
  355.   UnclipWindow( window, oldRegion ).
  356. *)
  357.  
  358. BEGIN (* ClipWindowToBorders *)
  359.   RETURN
  360.     ClipWindow
  361.       ( window, window.borderLeft, window.borderTop,
  362.         window.width - window.borderRight - 1,
  363.         window.height - window.borderBottom - 1, oldRegion );
  364. END ClipWindowToBorders;
  365.  
  366.  
  367. (*------------------------------------*)
  368. PROCEDURE UnclipWindow * (window : i.WindowPtr; prevRegion : gfx.RegionPtr);
  369. (*
  370.   Restores a window's clipping region after a call to ClipWindow() or
  371.   ClipWindowToBorders();
  372. *)
  373.  
  374. VAR
  375.   oldRegion : gfx.RegionPtr;
  376.  
  377. BEGIN (* UnclipWindow *)
  378.   oldRegion := l.InstallClipRegion (window.wLayer, prevRegion);
  379.   IF oldRegion # NIL THEN
  380.     gfx.DisposeRegion (oldRegion);
  381.   END
  382. END UnclipWindow;
  383.  
  384.  
  385. (*------------------------------------*)
  386. PROCEDURE DrawWidth * ( window : i.WindowPtr ) : INTEGER;
  387. (*
  388.   Returns the width of the window's inner drawing region.
  389. *)
  390.  
  391. BEGIN
  392.   RETURN (window.width - window.borderLeft - window.borderRight)
  393. END DrawWidth;
  394.  
  395.  
  396. (*------------------------------------*)
  397. PROCEDURE DrawHeight *
  398.   ( window : i.WindowPtr )
  399.   : INTEGER;
  400. (*
  401.   Returns the height of the window's inner drawing region.
  402. *)
  403.  
  404. BEGIN
  405.   RETURN (window.height - window.borderTop - window.borderBottom)
  406. END DrawHeight;
  407.  
  408.  
  409. (*------------------------------------*)
  410. PROCEDURE AdjustForBorders *
  411.   ( window : i.WindowPtr; VAR left, top : INTEGER );
  412. (*
  413.   Adjusts a window co-ordinate to ensure the origin is the top left of the
  414.   window's inner drawing region.
  415. *)
  416.  
  417. BEGIN (* AdjustForBorders *)
  418.   IF ~(i.gimmeZeroZero IN window.flags) THEN
  419.     INC( left, window.borderLeft); INC( top, window.borderTop)
  420.   END
  421. END AdjustForBorders;
  422.  
  423.  
  424. (*------------------------------------*)
  425. PROCEDURE StripIntuiMessages *
  426.   ( mp : e.MsgPortPtr; win : i.WindowPtr );
  427. (*
  428.   Function to remove and reply all IntuiMessages on a port that have
  429.   been sent to a particular window (note that we don't rely on the
  430.   lnSucc pointer of a message after we have replied it).
  431.  
  432.   This is from the RKM:Libraries, 3d Ed, p255.
  433. *)
  434.  
  435.   VAR msg : i.IntuiMessagePtr; succ : e.NodePtr;
  436.  
  437. BEGIN (* StripIntuiMessages *)
  438.   msg := SYS.VAL (i.IntuiMessagePtr, mp.msgList.head);
  439.   WHILE msg.execMessage.node.succ # NIL DO
  440.     succ := msg.execMessage.node.succ;
  441.     IF msg.idcmpWindow = win THEN
  442.       (*
  443.         Intuition is about to free this message.  Make sure that we have
  444.         politely sent it back.
  445.       *)
  446.       e.Remove (msg);
  447.       e.ReplyMsg (msg)
  448.     END;
  449.     msg := SYS.VAL (i.IntuiMessagePtr, succ)
  450.   END
  451. END StripIntuiMessages;
  452.  
  453. (*------------------------------------*)
  454. PROCEDURE CloseWindowSafely *
  455.   ( win : i.WindowPtr );
  456. (*
  457.   Strip all IntuiMessages from an IDCMP which are waiting for a specific
  458.   window.  When the messages are gone, set the UserPort of the window to
  459.   NIL and call ModifyIDCMP (win, {}).  This will free the Intuition
  460.   parts of the IDCMP and turn off messages to this port without changing
  461.   the original UserPort (which may be in use by other windows).
  462.  
  463.   This is from the RKM:Libraries, 3d Ed, p255.
  464. *)
  465.  
  466.   VAR
  467.  
  468. BEGIN (* CloseWindowSafely *)
  469.   (* We forbid here to keep out of race conditions with Intuition *)
  470.   e.Forbid ();
  471.  
  472.   (*
  473.     Send back any messages for this window that have not yet been processed
  474.   *)
  475.   StripIntuiMessages (win.userPort, win);
  476.  
  477.   (* Clear UserPort so Intuition will not free it *)
  478.   win.userPort := NIL;
  479.  
  480.   (* Tell Intuition to stop sending messages *)
  481.   i.OldModifyIDCMP (win, {});
  482.  
  483.   (* Turn multitasking back on *)
  484.   e.Permit ();
  485.  
  486.   (* Now it's safe to really close the window *)
  487.   i.CloseWindow (win)
  488. END CloseWindowSafely;
  489.  
  490. (*------------------------------------*)
  491. PROCEDURE FindSizeGadget *
  492.   ( win : i.WindowPtr; VAR width, height : INTEGER )
  493.   : BOOLEAN;
  494.  
  495.   CONST
  496.     Sizing = i.sysGadget + i.sizing;
  497.  
  498.   VAR gadget : i.GadgetPtr;
  499.  
  500. BEGIN (* FindSizeGadget *)
  501.   gadget := win.firstGadget;
  502.   WHILE (gadget # NIL) & (gadget.gadgetType # Sizing) DO
  503.     gadget := gadget.nextGadget
  504.   END;
  505.   IF gadget # NIL THEN
  506.     width := gadget.width; height := gadget.height
  507.   END;
  508.   RETURN (gadget # NIL)
  509. END FindSizeGadget;
  510.  
  511. (* ===== Requesters ===== *)
  512.  
  513. (*------------------------------------*)
  514.  
  515. <*$LongVars-*>
  516.  
  517. PROCEDURE MultiRequest *
  518.   ( window                     : i.WindowPtr;
  519.     VAR bodyText               : ARRAY OF e.APTR;
  520.     lines                      : INTEGER;
  521.     positiveText, negativeText : e.APTR )
  522.   : BOOLEAN;
  523.  
  524. CONST
  525.   NoFlags = {};
  526.   ExtraWidth = 32;
  527.   ExtraHeight = 22;
  528.  
  529. VAR
  530.   newTextPtr, bodyTextPtr, positiveTextPtr, negTextPtr : i.IntuiTextPtr;
  531.   positiveIntuiText, negativeIntuiText : i.IntuiText;
  532.   textHeight, maxLength, width, height : INTEGER;
  533.   memory : i.RememberPtr;
  534.   result : BOOLEAN;
  535.  
  536. BEGIN (* MultiRequest *)
  537.   IF (lines > 0) THEN
  538.     IF positiveText # NIL THEN
  539.       positiveIntuiText := autoIntuiText;
  540.       positiveIntuiText.iText := positiveText;
  541.       positiveTextPtr := SYS.ADR (positiveIntuiText);
  542.     ELSE
  543.       positiveTextPtr := NIL;
  544.     END;
  545.     IF negativeText # NIL THEN
  546.       negativeIntuiText := autoIntuiText;
  547.       negativeIntuiText.iText := negativeText;
  548.       negTextPtr := SYS.ADR (negativeIntuiText);
  549.     ELSE
  550.       RETURN FALSE
  551.     END;
  552.     memory := NIL;
  553.     bodyTextPtr := NIL;
  554.     maxLength := 0;
  555.     textHeight := PrefsFontHeight() + 1;
  556.     height := ((lines + 2) * textHeight) + ExtraHeight;
  557.     WHILE lines > 0 DO
  558.       newTextPtr := i.AllocRemember (memory, SIZE(i.IntuiText), {});
  559.       IF newTextPtr # NIL THEN
  560.         DEC (lines);
  561.         newTextPtr^ := autoIntuiText;
  562.         INC (newTextPtr^.topEdge, lines * textHeight);
  563.         newTextPtr.iText := bodyText [lines];
  564.         newTextPtr.nextText := bodyTextPtr;
  565.         maxLength :=
  566.           u.MaxInt
  567.             (maxLength, i.IntuiTextLength(newTextPtr^));
  568.         bodyTextPtr := newTextPtr;
  569.       ELSE
  570.         i.FreeRemember (memory, e.LTRUE);
  571.         RETURN FALSE;
  572.       END
  573.     END; (* WHILE *)
  574.     width := maxLength + ExtraWidth;
  575.     result :=
  576.       i.AutoRequest
  577.         ( window, bodyTextPtr, positiveTextPtr, negTextPtr, NoFlags,
  578.           NoFlags, width, height );
  579.     i.FreeRemember (memory, e.LTRUE);
  580.     RETURN result;
  581.   ELSE
  582.     RETURN FALSE;
  583.   END
  584. END MultiRequest;
  585.  
  586. <*$LongVars+*>
  587.  
  588. (*------------------------------------*)
  589. PROCEDURE SimpleRequest * (
  590.   window                               : i.WindowPtr;
  591.   bodyText, positiveText, negativeText : e.APTR )
  592.   : BOOLEAN;
  593.  
  594. VAR
  595.   bodyTextArray : ARRAY 1 OF e.APTR;
  596.  
  597. BEGIN (* SimpleRequest *)
  598.   IF bodyText # NIL THEN
  599.     bodyTextArray [0] := bodyText;
  600.     RETURN
  601.       MultiRequest (window, bodyTextArray, 1, positiveText, negativeText);
  602.   ELSE
  603.     RETURN FALSE;
  604.   END
  605. END SimpleRequest;
  606.  
  607.  
  608. (*------------------------------------*)
  609. PROCEDURE SimpleNotice *
  610.   ( window : i.WindowPtr; bodyText : e.APTR );
  611.  
  612. BEGIN (* SimpleNotice *)
  613.   SYS.PUTREG (0, SimpleRequest (window, bodyText, NIL, SYS.ADR("Continue")))
  614. END SimpleNotice;
  615.  
  616.  
  617. (*------------------------------------*)
  618. PROCEDURE MultiNotice *
  619.   ( window : i.WindowPtr; VAR bodyText : ARRAY OF e.APTR; lines : INTEGER );
  620.  
  621. BEGIN (* MultiNotice *)
  622.   SYS.PUTREG
  623.     (0, MultiRequest (window, bodyText, lines, NIL, SYS.ADR("Continue")))
  624. END MultiNotice;
  625.  
  626.  
  627. (* ===== Menus ===== *)
  628.  
  629.  
  630. (*------------------------------------*)
  631. PROCEDURE GetMenuChoice *
  632.   ( menuSelection  : INTEGER;
  633.     VAR firstMenu  : i.Menu;
  634.     VAR menuChoice : Choice );
  635.  
  636. BEGIN (* GetMenuChoice *)
  637.   menuChoice.menuChosen := (menuSelection MOD 32);
  638.   menuChoice.itemChosen := (SYS.LSH (menuSelection, -5) MOD 64);
  639.   menuChoice.subItemChosen := (SYS.LSH (menuSelection, -11) MOD 32);
  640.   menuChoice.pointer := i.ItemAddress (firstMenu, menuSelection);
  641. END GetMenuChoice;
  642.  
  643.  
  644. <*$LongVars-*>
  645.  
  646. BEGIN (* IntuiUtil *)
  647.   autoIntuiText.leftEdge  := i.autoLeftEdge;
  648.   autoIntuiText.topEdge   := i.autoTopEdge;
  649.   autoIntuiText.frontPen  := i.autoFrontPen;
  650.   autoIntuiText.backPen   := i.autoBackPen;
  651.   autoIntuiText.drawMode  := i.autoDrawMode;
  652.   autoIntuiText.iTextFont := i.autoITextFont;
  653.   autoIntuiText.iText     := NIL;
  654.   autoIntuiText.nextText  := i.autoNextText;
  655. END IntuiUtil.
  656.  
  657.